package picture

import (
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"hosptial-record/api/base"
	"hosptial-record/forms"
	"hosptial-record/global"
	"hosptial-record/global/response"
	"hosptial-record/model"
	"hosptial-record/utils/picture"
	"net/http"
	"os"
	"path/filepath"
	"sync"
)

func List(ctx *gin.Context) {
	var form forms.GetPictureListForm
	if err := ctx.ShouldBindQuery(&form); err != nil {
		base.HandleValidatorError(ctx, err)
		return
	}
	db := global.DB
	if form.PatientID != 0 {
		db = db.Where("patient_id = ?", form.PatientID)
	}
	if form.TypeID != 0 {
		db = db.Where("type_id = ?", form.TypeID)
	}
	var total int64
	var pictures []model.Picture
	res := global.DB.
		Model(&model.Picture{}).
		Count(&total).
		Scopes(base.Paginate(int(form.Page), int(form.PageSize))).
		Find(&pictures)
	if res.Error != nil {
		zap.S().Errorw("Picture [List] 查询图片列表失败", "msg", zap.Error(res.Error))
		ctx.JSON(http.StatusInternalServerError, response.BaseResponse{
			Msg:  "查询失败",
			Data: res.Error,
		})
	}
	ctx.JSON(http.StatusOK, response.ListResponse{
		Msg: "获取成功",
		Data: response.ListData{
			Data:  pictures,
			Total: total,
		},
	})
}

func Create(ctx *gin.Context) {
	var form forms.PictureForm
	if err := ctx.ShouldBindJSON(&form); err != nil {
		base.HandleValidatorError(ctx, err)
		return
	}
	picture := model.Picture{
		TypeID:    form.TypeID,
		Url:       form.Url,
		PatientID: form.PatientID,
	}
	res := global.DB.Create(&picture)
	if res.Error != nil {
		zap.S().Errorw("Picture [Create] 创建图片失败", "msg", zap.Error(res.Error))
		ctx.JSON(http.StatusInternalServerError, response.BaseResponse{
			Msg:  "创建失败",
			Data: res.Error,
		})
		return
	}
	ctx.JSON(http.StatusOK, response.BaseResponse{
		Msg:  "创建成功",
		Data: picture,
	})
}

func Update(ctx *gin.Context) {
	var form forms.EditPictureForm
	if err := ctx.ShouldBindJSON(&form); err != nil {
		base.HandleValidatorError(ctx, err)
		return
	}
	picture := model.Picture{
		TypeID:    form.TypeID,
		PatientID: form.PatientID,
	}
	picture.ID = form.ID
	res := global.DB.Updates(&picture)
	if res.Error != nil {
		zap.S().Errorw("Picture [Update] 更新图片失败", "msg", zap.Error(res.Error))
		ctx.JSON(http.StatusInternalServerError, response.BaseResponse{
			Msg:  "更新失败",
			Data: res.Error,
		})
		return
	}
	ctx.JSON(http.StatusOK, response.BaseResponse{
		Msg: "更新成功",
	})
}

func Delete(ctx *gin.Context) {
	id, err := base.GetID2Param(ctx)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, response.BaseResponse{
			Msg: "ID不合法",
		})
		return
	}
	tx := global.DB.Begin()
	var pic model.Picture
	pic.ID = id
	// 查询是否存在
	if res := tx.First(&pic); res.RowsAffected == 0 {
		ctx.JSON(http.StatusBadRequest, response.BaseResponse{
			Msg:  "删除的文件不存在",
			Data: res.Error,
		})
		return
	}
	res := tx.Unscoped().Delete(&pic)
	if res.Error != nil {
		zap.S().Errorw("Picture [Delete] 删除图片失败", "msg", zap.Error(res.Error))
		ctx.JSON(http.StatusInternalServerError, response.BaseResponse{
			Msg:  "删除失败",
			Data: res.Error,
		})
		// 回滚事务
		tx.Rollback()
		return
	}
	// 删除本地文件
	dir, _ := os.Getwd()
	if err := os.Remove(filepath.Join(dir, pic.Url)); err != nil {
		// 删除失败，需要回退
		zap.S().Errorw("Picture [Delete] 删除图片失败", "msg", zap.Error(err))
		ctx.JSON(http.StatusBadGateway, response.BaseResponse{
			Msg:  "删除失败",
			Data: err,
		})
		tx.Rollback()
		return
	}
	// 提交事务
	tx.Commit()
	ctx.JSON(http.StatusOK, response.BaseResponse{
		Msg: "删除成功",
	})
}

// PrintPicture 打印图片
func PrintPicture(ctx *gin.Context) {
	// TODO: 打印调用接口返回有水印的图片
	var form forms.PrintPictureForm
	if err := ctx.ShouldBind(&form); err != nil {
		base.HandleValidatorError(ctx, err)
		return
	}
	// 查询图片
	var pics []model.Picture
	if res := global.DB.Select("url").Find(&pics, form.PID); res.Error != nil {
		zap.S().Errorw("Picture [PrintPicture] 查找图片失败:", "msg", res.Error)
		ctx.JSON(http.StatusBadGateway, response.BaseResponse{
			Msg:  "查询图片失败",
			Data: res.Error,
		})
		return
	}
	wg := sync.WaitGroup{}
	wg.Add(len(pics))
	var res []model.Picture
	// 开始生成水印
	for _, val := range pics {
		tmp := val
		go func() {
			img, err := picture.GenerateWaterMark(tmp.Url)
			if err != nil {
				// 生成水印失败
				zap.S().Errorw("Picture [PrintPicture] 失败:", "msg", err)
				ctx.JSON(http.StatusBadGateway, response.BaseResponse{
					Msg:  "生成水印失败",
					Data: err,
				})
				return
			}
			res = append(res, model.Picture{
				BaseModel: model.BaseModel{
					ID:        tmp.ID,
					CreatedAt: tmp.CreatedAt,
				},
				TypeID:    tmp.TypeID,
				Url:       img,
				PatientID: tmp.PatientID,
			})
			wg.Done()
		}()
	}
	wg.Wait()
	ctx.JSON(http.StatusOK, response.ListResponse{
		Msg: "生成成功",
		Data: response.ListData{
			Total: int64(len(res)),
			Data:  res,
		},
	})
}
